﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using System.Threading;

namespace arduinodimmer
{
    public partial class Form1 : Form
    {
        private static int step = 10;
        private static int stepTime = 10;
        private static SerialPort comPort = new SerialPort();
        private static Constants con = new Constants();
        public Form1()
        {
            InitializeComponent();
            comPort.PortName = "COM6";
            comPort.BaudRate=9600;
            comPort.DataReceived += OnReceived;
            comPort.Open();
            progressBar1.Value = step;
            

        }

        private bool stepDiagonal(int up, int left)
        {
            int leftStep = pbBall.Left - left;
            int upStep = pbBall.Top - up;

            int maxStep = (Math.Abs(leftStep) > Math.Abs(upStep)) ? Math.Abs(leftStep) : Math.Abs(upStep);
            int sleepTime = stepTime / maxStep;

            int leftStepSize = 1;
            int upStepSize = 1;
            for (int i = 0; i < maxStep; i++)
            {
                if (leftStep < 0)
                    leftStepSize = -1;
                if (upStep < 0)
                    upStepSize = -1;

                stepLeft(pbBall.Left + leftStepSize, false);
                stepUp(pbBall.Top + upStepSize, false);

            }
            return true;
        }
        private bool stepLeft(int left, bool pause=true)
        {

            
            int stepSize=1;
            int leftStep = pbBall.Left - left;
            if (leftStep == 0)
                return false;
            int sleepTime = stepTime / Math.Abs(leftStep); 
            
            if (leftStep < 0)
                stepSize = -1;

            for (int i = 0; i < Math.Abs(leftStep); i++)
            {
                if ((pbBall.Left + pbBall.Width ) == this.Width && stepSize == 1)
                    return false;
                else if (pbBall.Left == 0 && stepSize == -1)
                    return false;
                pbBall.Left = pbBall.Left + stepSize;
                if(pause)
                    Thread.Sleep(sleepTime);
            }

            return true;

        }

        private bool stepUp(int up, bool pause=true)
        {


            int stepSize = 1;
            int upStep = pbBall.Top - up;
            if (upStep ==0) return false;
            int sleepTime = stepTime / Math.Abs(upStep);
            if (upStep < 0)
                stepSize = -1;

            for (int i = 0; i < Math.Abs(upStep); i++)
            {
                if ((pbBall.Top + pbBall.Height+pbBall.Height/2)== this.Height && stepSize == 1)
                    return false;
                else if (pbBall.Top == 0 && stepSize == -1)
                    return false;
                pbBall.Top = pbBall.Top + stepSize;
                if(pause)
                    Thread.Sleep(sleepTime);
            }

            return true;
        }

        private void updateOutput(string text, int textNum)
        {
            txtOutput.Text = text;
            switch (textNum)
            {
                case (int)Constants.IRCodes.ARROW_UP:
                    stepUp(pbBall.Top+step);
                    break;

                case (int)Constants.IRCodes.ARROW_DOWN:
                    stepUp(pbBall.Top - step);
                    break;
                case (int)Constants.IRCodes.ARROW_LEFT:
                    stepLeft(pbBall.Left + step);
                    break;

                case (int)Constants.IRCodes.ARROW_RIGHT:
                    stepLeft(pbBall.Left - step);
                    break;
                case (int)Constants.IRCodes.FAVES:
                    stepDiagonal(pbBall.Top - step, pbBall.Left + step);
                    break;
                case (int)Constants.IRCodes.LIST:
                    stepDiagonal(pbBall.Top + step, pbBall.Left - step);
                    break;
                case (int)Constants.IRCodes.INFO:
                    stepDiagonal(pbBall.Top + step, pbBall.Left + step);
                    break;
                case (int)Constants.IRCodes.GUIDE:
                    stepDiagonal(pbBall.Top - step, pbBall.Left - step);
                    break;
                case(int)Constants.IRCodes.VOLUME_UP:
                    step = step + 2;
                    break;
                case (int)Constants.IRCodes.VOLUME_DOWN:
                    step = step - 2;
                    break;
                case (int)Constants.IRCodes.CHANNEL_UP:
                    this.Top = this.Top - 2;
                    break;
                case (int)Constants.IRCodes.CHANNEL_DOWN:
                    this.Top = this.Top + 2;
                    break;
                case(int)Constants.IRCodes.FAST_FORWARD:
                    while (stepLeft(pbBall.Left -110))
                    { }
                    break;
                case (int)Constants.IRCodes.REWIND:
                    while (stepLeft(pbBall.Left + 110))
                    {}
                    break;

            }
            if (step > 100) step = 100;
            if (step < 0) step = 0;
            progressBar1.Value = step;
            this.Refresh();

        }

        public delegate void updateOutputCallback(string text, int textNum);

        private  void OnReceived(object sender, SerialDataReceivedEventArgs c)
        {
            int ch;
            try
            {
                 
                // write out text coming back from the arduino
                string text = comPort.ReadLine();
                text = text.Substring(0, text.IndexOf("\r"));
                int textNum = Convert.ToInt32(text);
                try
                {
                    text = con.IRValueDisplayNames[Convert.ToInt32(text)];
                }
                catch (Exception e)
                {
                    text = "?: " + text;

                }
                
                txtOutput.Invoke(new updateOutputCallback(this.updateOutput),
                    new object[] { text, textNum });
                //MessageBox.Show("Arduino said " + text);
            }
            catch (Exception exc) {
                MessageBox.Show(exc.Message);
            }
        }

        private void txtOutput_TextChanged(object sender, EventArgs e)
        {

        }
    }
}
